﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Sasa.QualityTools.CodeAnalysis.Common;

namespace Sasa.QualityTools.CodeAnalysis.FxCopIntegrator.ViewModels
{
    public abstract class CodeAnalysisResultGridViewModelBase : ViewModelBase
    {
        private const string SettingVersion = "2.0";

        protected abstract string SettingPath { get; }

        protected abstract IEnumerable<DataGridColumnViewModel> DataGridColumnViewModels { get; }


        public abstract void Reset();

        public void Save()
        {
            var xml = new XmlDocument();
            xml.AppendChild(xml.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            var root = xml.AppendChild(xml.CreateElement(GetType().Name));
            root.Attributes.Append(xml.CreateAttribute("Version")).Value = SettingVersion;

            foreach (var model in DataGridColumnViewModels.OrderBy(o => o.DisplayIndex))
            {
                var element = root.AppendChild(xml.CreateElement(model.PropertyName));
                element.Attributes.Append(xml.CreateAttribute("IsVisible")).Value = model.IsVisible.ToString();
                element.Attributes.Append(xml.CreateAttribute("DisplayIndex")).Value = model.DisplayIndex.ToString();
                element.Attributes.Append(xml.CreateAttribute("Width")).Value = model.Width.ToString();
                root.AppendChild(element);
            }

            try
            {
                xml.Save(SettingPath);
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Failed to save code analysis result grid state to '{0}'.", SettingPath);
            }
        }

        public void Load()
        {
            try
            {
                var xml = new XmlDocument();
                xml.Load(SettingPath);

                var root = xml.SelectSingleNode("/" + GetType().Name);
                if (root == null)
                {
                    Logger.Error("The root element of code analysis result grid state wasn't found.");
                    return;
                }

                foreach (var model in DataGridColumnViewModels)
                {
                    Buildup(model, root.SelectSingleNode(model.PropertyName));
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Failed to load code analysis result grid state from '{0}'.", SettingPath);
                Reset();
            }
        }

        private void Buildup(DataGridColumnViewModel model, XmlNode node)
        {
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            if (node == null)
            {
                Logger.Warn("The xml node for '{0}' wasn't found.", model.PropertyName);
                return;
            }

            var isVisible = node.SelectSingleNode("@IsVisible");
            if (isVisible != null)
            {
                bool value;
                if (Boolean.TryParse(isVisible.Value, out value))
                {
                    model.IsVisible = value;
                }
                else
                {
                    Logger.Warn("The value of IsVisible attribute ({0}) couldn't be parsed.", isVisible.Value);
                }
            }

            var displayIndex = node.SelectSingleNode("@DisplayIndex");
            if (displayIndex != null)
            {
                int value;
                if (Int32.TryParse(displayIndex.Value, out value))
                {
                    model.DisplayIndex = value;
                }
                else
                {
                    Logger.Warn("The value of DisplayIndex attribute ({0}) couldn't be parsed.", displayIndex.Value);
                }
            }

            var width = node.SelectSingleNode("@Width");
            if (width != null)
            {
                double value;
                if (Double.TryParse(width.Value, out value))
                {
                    model.Width = value;
                }
                else
                {
                    Logger.Warn("The value of Width attribute ({0}) couldn't be parsed.", width.Value);
                }
            }
        }
    }
}
